package com.demoCode.gateway.exception;

import cn.dev33.satoken.exception.SaTokenException;
import com.demoCode.common.common.BaseResponse;
import com.demoCode.common.common.ErrorCode;
import com.demoCode.common.common.ResultUtils;
import com.demoCode.common.exception.BusinessException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Slf4j
public class GatewayExceptionHandler implements ErrorWebExceptionHandler {

    private final ObjectMapper objectMapper = new ObjectMapper();

    @NotNull
    @Override
    public Mono<Void> handle(ServerWebExchange serverWebExchange, @NotNull Throwable throwable) {
        // 获取请求
        ServerHttpRequest request = serverWebExchange.getRequest();
        // 获取响应
        ServerHttpResponse response = serverWebExchange.getResponse();
        // 通用错误码 默认系统异常
        BaseResponse<?> baseResponse = new BaseResponse<>();
        log.error("网关异常处理: {}, 请求路径: {}", throwable.getMessage(), request.getPath());
        // 校验saToken抛出的权限异常
        if (throwable instanceof SaTokenException){
            // 无权限
            baseResponse.setCode(ErrorCode.NO_AUTH_ERROR.getCode());
        } else if (throwable instanceof BusinessException){
            // 业务异常
            BusinessException businessException = (BusinessException) throwable;
            baseResponse = ResultUtils.error(businessException.getCode(), throwable.getMessage());
        } else {
            baseResponse = ResultUtils.error(ErrorCode.SYSTEM_ERROR);
        }
        // 写入响应内容
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        // 返回错误信息
        BaseResponse<?> finalBaseResponse = baseResponse;
        return response.writeWith(Mono.fromSupplier(() -> {
            DataBufferFactory dataBufferFactory = response.bufferFactory();
            byte[] bytes = null;
            try {
                bytes = objectMapper.writeValueAsBytes(finalBaseResponse);
            } catch (JsonProcessingException e) {
                log.error("网关异常处理失败", e);
            }
            assert bytes != null;
            return dataBufferFactory.wrap(bytes);
        }));
    }
}
